package com.egreen.user.controller;

import com.egreen.common.Result;
import com.egreen.common.States;
import com.egreen.common.pojo.DTO.user.loginaccount.*;
import com.egreen.common.pojo.DTO.user.validation.ValidateCodeDTO;
import com.egreen.common.pojo.entity.user.User;
import com.egreen.common.serviceapi.system.VerificationCodeAPI;
import com.egreen.user.service.IUserLoginAccountService;
import com.egreen.user.service.IUserService;
import com.egreen.user.service.api.impl.UserServiceApi;
import com.egreen.user.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author cloudJiang
 * @since 2022-07-16
 */
@RestController
@RequestMapping("/userLoginAccount")
@Api(tags = "用户登录以及登录相关信息修改接口")
public class UserLoginAccountController {
    @Autowired
    IUserLoginAccountService loginAccountService;
    @Autowired
    JwtUtil jwtUtil;
    @Autowired
    UserServiceApi userServiceApi;
    @Autowired
    IUserService userService;

    @DubboReference
    VerificationCodeAPI verificationCodeAPI;


    /**
     * 通过密码登录
     *
     * @return
     */
    @ApiOperation(value = "密码登录", notes = "通过调用loginByPassword方法，使用手机号或者邮箱配合密码进行登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "loginKey", value = "用户登录的手机号或邮箱", required = true),
            @ApiImplicitParam(name = "password", value = "登录密码", required = true),
            @ApiImplicitParam(name = "loginByPasswordDTO", value = "以上属性被封装到这个DTO里")
    })
    @PostMapping("/loginByPassword")
    Result loginByPassword(@Validated @RequestBody LoginByPasswordDTO loginByPasswordDTO) {
        //进行登录流程，成功登录则生成jwt并返回给前端
        User user = loginAccountService.loginByPassword(loginByPasswordDTO);
        String token = jwtUtil.createTokenWhenLogin(user.getId(), user.getStates());
        return Result.OK(new String[]{token, String.valueOf(user.getId()), String.valueOf(user.getStates()),
                String.valueOf(user.getLocationId())});
    }


    /**
     * 通过验证码登录
     *
     * @return
     */
    @ApiOperation(value = "验证码登录", notes = "通过调用loginByValidCode方法，使用手机号或者邮箱配合验证码进行登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "loginKey", value = "用户登录的手机号或邮箱", required = true),
            @ApiImplicitParam(name = "code", value = "验证码", required = true),
            @ApiImplicitParam(name = "loginByValidCodeDTO", value = "以上属性被封装到这个DTO里")
    })
    @PostMapping("/loginByValidCode")
    Result loginByValidCode(@Validated @RequestBody ValidateCodeDTO validateCodeDTO) {
        //进行登录流程，成功登录则生成jwt并返回给前端
        User user = loginAccountService.loginByValidCode(validateCodeDTO);
        String token = jwtUtil.createTokenWhenLogin(user.getId(), user.getStates());
        return Result.OK(new String[]{token, String.valueOf(user.getId()), String.valueOf(user.getStates()), String.valueOf(user.getLocationId()),
                String.valueOf(user.getLocationId())});
    }

    /**
     * 用户退出登录
     *
     * @return
     */
    @ApiOperation(value = "退出登录", notes = "将token传入，解析后根据解析信息退出登录（解析过程中顺带验证是否是有效登录）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "用户登录时存储的token", required = true),
    })
    @PostMapping("/logout")
    Result logout(@RequestHeader("Token") String token) {
        //首先解析token，之后调用jwtUtil的方法将token在redis中删除
        Claims claims = jwtUtil.checkJwt(token);
        Object userId = claims.get("userId");
        jwtUtil.deleteJwtFromRedis(userId);
        return Result.OK();
    }

    /**
     * 在修改密码前进行旧密码比对
     *
     * @return
     */
    @ApiOperation(value = "验证旧密码", notes = "通过调用validOldPassword方法，使用用户ID来验证旧密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户ID", paramType = "int", required = true),
            @ApiImplicitParam(name = "password", value = "旧密码", required = true),
            @ApiImplicitParam(name = "validOldPasswordDTO", value = "以上两个参数封装在此DTO中")
    })
    @PostMapping("/validOldPassword")
    Result validOldPassword(@Validated @RequestBody ValidOldPasswordDTO validOldPasswordDTO) {
        loginAccountService.validOldPassword(validOldPasswordDTO);
        return Result.OK(States.OK);
    }

    /**
     * 发送验证码
     *
     * @return
     */
    @ApiOperation(value = "发送验证码", notes = "将验证码发送到传入的手机号或邮箱中")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sendTo", value = "用户登录的手机号或邮箱", required = true)
    })
    @GetMapping("/sendCode")
    Result sendCode(@RequestParam("sendTo") String sendTo) {
        userServiceApi.sendValidCodeSms(sendTo);
        return Result.OK();
    }

    /**
     * 验证验证码
     *
     * @return
     */
    @ApiOperation(value = "验证验证码", notes = "验证验证码是否正确")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sendTo", value = "用户登录的手机号或邮箱", required = true),
            @ApiImplicitParam(name = "validCode", value = "验证码", required = true)
    })
    @GetMapping("/validCode")
    Result validCode(@RequestParam("sendTo") String sendTo, @RequestParam("validCode") String validCode) {
        return Result.OK(userService.comparisonValidCode(sendTo, validCode));
    }

    /**
     * 重置用户密码
     *
     * @return
     */
    @ApiOperation(value = "重置用户密码", notes = "通过调用resetPassword方法使用password和loginAccountId两个参数来重置密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "password", value = "用户密码", required = true),
            @ApiImplicitParam(name = "userId", value = "用户的登录账户ID", required = true),
            @ApiImplicitParam(name = "resetPasswordDTO", value = "以上两个参数封装在此DTO中")
    })
    @PostMapping("/resetPassword")
    Result resetPassword(@Validated @RequestBody ResetPasswordDTO resetPasswordDTO) {
        loginAccountService.resetPassword(resetPasswordDTO.getPassword(), resetPasswordDTO.getUserId());
        return Result.OK(States.OK);
    }

    /**
     * 修改用户手机号
     *
     * @return
     */
    @ApiOperation(value = "修改用户手机号", notes = "通过调用resetPhone方法，使用accountId以及phone两个参数来重置手机号码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户的账户ID", paramType = "Long", required = true),
            @ApiImplicitParam(name = "phone", value = "用户手机号", required = true),
            @ApiImplicitParam(name = "resetPhoneDTO", value = "以上两个参数封装在此DTO中")
    })
    @PostMapping("/resetPhone")
    Result resetPhone(@Validated @RequestBody ResetPhoneDTO resetPhoneDTO) {
        loginAccountService.resetPhone(resetPhoneDTO.getUserId(), resetPhoneDTO.getPhone());
        return Result.OK(States.OK);
    }

    /**
     * 修改用户邮箱
     *
     * @return
     */
    @ApiOperation(value = "修改用户邮箱", notes = "通过调用resetEmail方法，使用accountId以及email两个参数来重置手机号码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户的账户ID", paramType = "Long", required = true),
            @ApiImplicitParam(name = "email", value = "用户邮箱", required = true),
            @ApiImplicitParam(name = "resetEmailDTO", value = "以上两个参数封装在此DTO中")
    })
    @PostMapping("/resetEmail")
    Result resetEmail(@Validated @RequestBody ResetEmailDTO resetEmailDTO) {
        loginAccountService.resetEmail(resetEmailDTO.getUserId(), resetEmailDTO.getEmail());
        return Result.OK(States.OK);
    }

    /**
     * 获取用户手机号 不进行脱敏处理
     *
     * @return
     */
    @ApiOperation(value = "获取用户手机号，不脱敏", notes = "通过调用getTurePhone方法，使用userId数来获取用户手机号码(不进行脱敏处理)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户的账户ID", paramType = "Long", required = true)
    })
    @GetMapping("/getTurePhone")
    Result getTurePhone(Long userId) {
        return new Result(loginAccountService.getTurePhone(userId),
                States.OK.getStates(), States.OK.getDescription());
    }

    /**
     * 获取用户手机号 进行脱敏处理（返回的字符串中间四位使用*号代替)
     *
     * @return
     */
    @ApiOperation(value = "获取用户手机号，脱敏", notes = "通过调用getPhone方法，使用accountId数来获取用户手机号码(进行脱敏处理)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户的账户ID", paramType = "Long", required = true)
    })
    @GetMapping("/getPhone")
    Result getPhone(Long userId) {
        return new Result(loginAccountService.getPhone(userId),
                States.OK.getStates(), States.OK.getDescription());
    }

    /**
     * 获取用户邮箱
     *
     * @return
     */
    @ApiOperation(value = "获取用户邮箱", notes = "通过调用getEmail方法，使用accountId数来获取用户邮箱")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户的账户ID", paramType = "Long", required = true)
    })
    @GetMapping("/getEmail")
    Result getEmail(Long userId) {
        return new Result(loginAccountService.getEmail(userId),
                States.OK.getStates(), States.OK.getDescription());
    }

}

